#////////////////////////////////////////////////////////////////
# (c) Copyright 2008 by Jeongnim Kim
#////////////////////////////////////////////////////////////////
#////////////////////////////////////////////////////////////////
#   Jeongnim Kim
#   National Center for Supercomputing Applications &
#   Materials Computation Center
#   University of Illinois, Urbana-Champaign
#   Urbana, IL 61801
#   e-mail: jnkim@ncsa.uiuc.edu
#
# Supported by 
#   National Center for Supercomputing Applications, UIUC
#////////////////////////////////////////////////////////////////
project(kicker)

cmake_minimum_required(VERSION 2.6.2 FATAL_ERROR)
enable_language (Fortran)

SET(CMAKE_FALLBACK FALSE)
if(${CMAKE_MINOR_VERSION} VERSION_LESS "8")
  MESSAGE(WARNING ">>>> Recommend using cmake version 2.8.0 and higher. Using old cmake scripts. <<<< ")
  SET(CMAKE_FALLBACK TRUE)
endif(${CMAKE_MINOR_VERSION} VERSION_LESS "8")

# make sure that the default is a RELEASE
if (NOT CMAKE_BUILD_TYPE)
  set (CMAKE_BUILD_TYPE RELEASE CACHE STRING
    "Choose the type of build, options are: None Debug Release."
    FORCE)
endif (NOT CMAKE_BUILD_TYPE)

set(LIBRARY_OUTPUT_PATH ${PROJECT_BINARY_DIR}/lib 
  CACHE PATH "Single output directory for building all libraries.")
set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin 
  CACHE PATH "Single output directory for building all exceutables.")

######################################################################
# build include and library paths required for the projects
# For XYZ library, set an environment as
# export XYZ_HOME='root-of-the-library'
# XYZ_HOME/include
# XYZ_HOME/lib
# IF XYZ library is found, XYZ_FOUND is set to true
#
# find_package is used with cmake 2.8 and higher
######################################################################
SET(APP_INCLUDE_PATHS 
  $ENV{HDF5_HOME}/include 
  $ENV{HDF5_DIR}/include 
  $ENV{FFTW_HOME}/include
  $ENV{LIBXML2_HOME}/include
  $ENV{BOOST_HOME}
  )
SET(APP_LIBRARY_PATHS 
  $ENV{HDF5_HOME}/lib 
  $ENV{HDF5_DIR}/lib 
  $ENV{FFTW_HOME}/lib
  $ENV{LIBXML2_HOME}/lib
  )

##############################################################
# cmake cache values 
# -DENABLE_xyz=0|1
##############################################################
set(ENABLE_OPENMP 1 CACHE BOOL "Enable OpenMP: always true")
set(ENABLE_MPI 1 CACHE BOOL "Enable MPI. If wish to disable, -DENABLE_MPI=0")
set(ENABLE_SHMEM 0 CACHE BOOL "Disable SHMEM.")
set(ENABLE_FORTRAN 0 CACHE BOOL "Disable FORTRAN")
##############################################################
# macros: src/config.h
##############################################################
set(QMC_BITS 64)
set(QMC_CUDA 0)
set(QMC_DIM 3)
set(QMC_INDEXTYPE int)
set(QMC_PRECISION double)

##############################################################
# set the basic features
##############################################################
set(ENABLE_OPENMP 1 CACHE BOOL "Enable OpenMP")
set(ENABLE_FORTRAN 0 CACHE BOOL "Enable Fortran")
set(HAVE_MPI 1 CACHE BOOL "Have MPI")
set(HAVE_LIBXML2 0)
set(HAVE_LIBXMLPP 0)
set(HAVE_LIBHDF5 0)
set(HAVE_LIBSPRNG 0)
set(HAVE_LIBBLITZ 0)
set(HAVE_LIBFFTW 0)
set(HAVE_LIBMKL 0)
set(HAVE_LIBP3DFFT 0)

##############################################################
# profiler 
##############################################################
set(USE_LIBHPM 0 CACHE BOOL "Use IBM libhpm profiler")

##############################################################
# Now, fun begins
##############################################################
# set the directory where local *.cmake files are installed
# some options on SSE are commented out for now
set(PROJECT_CMAKE  ${PROJECT_SOURCE_DIR}/CMake)
list(APPEND CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/CMake ${PROJECT_SOURCE_DIR}/CMake/cuda)

include(CheckFunctionExists)
include(CheckIncludeFile)
include(CheckTypeSize)
include(TestCXXAcceptsFlag)
include(CheckCCompilerFlag)
check_include_file(stddef.h HAVE_STDDEF_H)
check_include_file(stdlib.h HAVE_STDLIB_H)
#check_include_file(inttypes.h HAVE_INTTYPES_H)
#check_include_file(memory.h HAVE_MEMORY_H)
#check_include_file(pmmintrin.h HAVE_PMMINTRIN_H)
#check_include_file(emmintrin.h HAVE_EMMINTRIN_H)
#check_include_file(sys/stat.h HAVE_SYS_STAT_H)
#check_include_file(sys/time.h HAVE_SYS_TIME_H)
#check_include_file(sys/types.h HAVE_SYS_TYPES_H)
#check_include_file(unistd.h HAVE_UNISTD_H)
check_function_exists(posix_memalign HAVE_POSIX_MEMALIGN)

##########################################################################
# Setting the compiler options
# COMPILER choose one of the cmake files to customize the compiler options
# If nothing is chosen, default settings by cmake will  be used.
##########################################################################
######################################################
# now set the compiler flags and the macros in src/config.h
######################################################
IF(CMAKE_TOOLCHAIN_FILE)
  MESSAGE(STATUS "-- Using ${CMAKE_TOOLCHAIN_FILE} toolchain ")
ELSE(CMAKE_TOOLCHAIN_FILE)
  #fun begins
  SET(FOUND_CXXENV 0)
  SET(ENABLE_OPENMP 0)
  SET(HAVE_MPI 0)
  SET(INTEL_COMPILER 0)
  SET(HAVE_MKL 0)
  SET(HAVE_MKL_VML 0)
  SET(HAVE_ACML 0)
  SET(HAVE_SSE 0)
  SET(HAVE_SSE2 0)
  SET(HAVE_SSE3 0)
  SET(HAVE_SSSE3 0)
  SET(USE_PREFETCH 0)
  SET(PREFETCH_AHEAD 12)
  SET(HAVE_C_VARARRAYS 1)

  ######################################################
  # Try to identify CPU identity
  ######################################################
  SET(CPU_IDENTITY "generic")
  INCLUDE(${PROJECT_CMAKE}/CheckProcessorID.cmake)

  #------------------------------------
  # On Jaguar use CrayXT.cmake
  #------------------------------------
  IF($ENV{HOST} MATCHES "jaguar")
    MESSAGE("  Working on jaguar. Using CMake/CrayXT.cmake")	 
    SET(CPU_IDENTITY "barcelona")
    INCLUDE(${PROJECT_CMAKE}/CrayXT.cmake)
    SET(FOUND_CXXENV 1)
    SET(CMAKE_SKIP_RPATH TRUE)
  ENDIF($ENV{HOST} MATCHES "jaguar")

  #------------------------------------
  # Check if using IBM compilers
  #------------------------------------
  IF($ENV{CXX} MATCHES "xlC")
    INCLUDE(${PROJECT_CMAKE}/IBMCompilers.cmake)
    SET(FOUND_CXXENV 1)
  ENDIF($ENV{CXX} MATCHES "xlC")

  #------------------------------------
  # Check if using Intel compilers
  #------------------------------------
  IF($ENV{CXX} MATCHES "icpc")
    INCLUDE(${PROJECT_CMAKE}/IntelCompilers.cmake)
    SET(FOUND_CXXENV 1)
  ENDIF($ENV{CXX} MATCHES "icpc")

  #------------------------------------
  # other compilers, e.g., mpicxx 
  # most likely *unix with gnu or intel compilers
  # using "-restrict" option to find out if intel compilers are backend.
  #------------------------------------
  IF(NOT FOUND_CXXENV)
    IF(CMAKE_COMPILER_IS_GNUCXX)
      INCLUDE(${PROJECT_CMAKE}/GNUCompilers.cmake)
    ELSE(CMAKE_COMPILER_IS_GNUCXX)
      SET(CMAKE_TRY_INTEL_CXX_FLAGS "-restrict")
      CHECK_CXX_ACCEPTS_FLAG(${CMAKE_TRY_INTEL_CXX_FLAGS} INTEL_CXX_FLAGS)
      IF(INTEL_CXX_FLAGS)
        INCLUDE(${PROJECT_CMAKE}/IntelCompilers.cmake)
        SET(FOUND_CXXENV 1)
      ENDIF(INTEL_CXX_FLAGS)
    ENDIF(CMAKE_COMPILER_IS_GNUCXX)
  ENDIF(NOT FOUND_CXXENV)

  #-------------------------------------------------------------------
  #  check MPI installation
  #-------------------------------------------------------------------
  #IF(QMC_MPI)
    ## mpi compilers
    if($ENV{CXX} MATCHES "mp")
      SET(HAVE_MPI 1)
      SET(HAVE_OOMPI 1)
      SET(MPI_FOUND TRUE)
    else($ENV{CXX} MATCHES "mp")
      include(FindMPI)
      IF(MPI_FOUND)
        MESSAGE(STATUS "Found mpi.h and libraries. Check for working mpi compiler ")
        FILE(WRITE ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testmpi.cxx 
          "#include <mpi.h>"
          "int main(int argc, char** argv){MPI_Init(&argc,&argv); MPI_Finalize();return 0;}\n")
        TRY_COMPILE(MPI_WORKS ${CMAKE_BINARY_DIR} 
          ${CMAKE_BINARY_DIR}${CMAKE_FILES_DIRECTORY}/CMakeTmp/testmpi.cxx
          OUTPUT_VARIABLE OUTPUT)
        IF(MPI_WORKS)
          MESSAGE(STATUS "MPI is enabled")
          SET(HAVE_MPI 1)
          SET(HAVE_OOMPI 1)
          LINK_LIBRARIES(${MPI_LIBRARY})
        ELSE(MPI_WORKS)
          MESSAGE(STATUS "MPI is disabled")
          SET(HAVE_MPI 0)
          SET(HAVE_OOMPI 0)
        ENDIF(MPI_WORKS)
      ENDIF(MPI_FOUND)
    endif($ENV{CXX} MATCHES "mp")
    #ENDIF(QMC_MPI)

  #-------------------------------------------------------------------
  # check lapack/blas
  #-------------------------------------------------------------------
  INCLUDE(${PROJECT_CMAKE}/FindLapack.cmake)
  IF(FOUND_MKL)
    SET(HAVE_LIBMKL 1)
  ENDIF(FOUND_MKL)
    
ENDIF(CMAKE_TOOLCHAIN_FILE)

#add fortran stuff
#include(Fortran)

SET(HAVE_OOMPI ${HAVE_MPI})
INCLUDE(${CMAKE_ROOT}/Modules/FindThreads.cmake)
####################################################################
#First check the required libraries. Abort if these are not found.
#Changed the fall-back versions to use similar conventions to 2.8.0 and higher
####################################################################
# use customized cmake file for boost so that we can deal with multiple
# installataions
INCLUDE(${PROJECT_CMAKE}/FindBoost.cmake)
INCLUDE(${PROJECT_CMAKE}/FindFFTW.cmake)
if(CMAKE_FALLBACK)
  INCLUDE(${PROJECT_CMAKE}/FindLibxml2.cmake)
  INCLUDE(${PROJECT_CMAKE}/FindHDF5.cmake)
  INCLUDE(${PROJECT_CMAKE}/FindZLIB.cmake)
  INCLUDE(${PROJECT_CMAKE}/FindSZLIB.cmake)
else()
  find_package(LibXml2)
  find_package(HDF5)
endif()

IF(LIBXML2_FOUND)
  INCLUDE_DIRECTORIES(${LIBXML2_INCLUDE_DIR})
  LINK_LIBRARIES(${LIBXML2_LIBRARIES})
  SET(HAVE_LIBXML2 1)
ENDIF(LIBXML2_FOUND)

IF(HDF5_FOUND)
  SET(HAVE_LIBHDF5 1)
  INCLUDE_DIRECTORIES(${HDF5_INCLUDE_DIR})
  LINK_LIBRARIES(${HDF5_LIBRARIES})
  IF(ZLIB_FOUND)
    LINK_LIBRARIES(${ZLIB_LIBRARIES})
  ENDIF(ZLIB_FOUND)
  IF(SZLIB_FOUND)
    LINK_LIBRARIES(${SZLIB_LIBRARIES})
  ENDIF(SZLIB_FOUND)
#ELSE(HDF5_FOUND)
#  MESSAGE(FATAL_ERROR "Require hdf5 1.6.4 or higher. Set HDF5_HOME")
ENDIF(HDF5_FOUND)

IF(Boost_FOUND)
  SET(HAVE_LIBBOOST 1)
  MESSAGE(STATUS "Setting Boost_INCLUDE_DIR="${Boost_INCLUDE_DIR})
  INCLUDE_DIRECTORIES(${Boost_INCLUDE_DIR})
#ELSE()
#  MESSAGE(FATAL_ERROR "Require boost 1.33.x or higher. Set BOOST_HOME")
ENDIF()

IF(FFTW_FOUND)
  set(HAVE_LIBFFTW 1)
  include_directories(${FFTW_INCLUDE_DIR})
  link_libraries(${FFTW_LIBRARIES})
ENDIF(FFTW_FOUND)

IF(HAVE_MPI)
INCLUDE(${PROJECT_CMAKE}/FindP3DFFT.cmake)
IF(P3DFFT_FOUND)
  INCLUDE_DIRECTORIES(${P3DFFT_INCLUDE_DIR})
  LINK_LIBRARIES(${P3DFFT_LIBRARY})
  SET(HAVE_LIBP3DFFT 1)
ENDIF(P3DFFT_FOUND)
ENDIF(HAVE_MPI)

set (CMAKE_CXX_FLAGS_MINSIZEREL "-DNDEBUG")
set (CMAKE_C_FLAGS_MINSIZEREL   "-DNDEBUG")
set (CMAKE_CXX_FLAGS_RELEASE    "-DNDEBUG")
set (CMAKE_C_FLAGS_RELEASE      "-DNDEBUG")

message(STATUS "CXX      compiler flags:" ${CMAKE_CXX_FLAGS})
message(STATUS "CC       compiler flags:" ${CMAKE_C_FLAGS})
message(STATUS "Fortran  compiler flags:" ${CMAKE_Fortran_FLAGS})


include_directories(${PROJECT_SOURCE_DIR}/src)
include_directories(${PROJECT_BINARY_DIR}/src)

configure_file(${PROJECT_SOURCE_DIR}/src/config.h.cmake.in
               ${PROJECT_BINARY_DIR}/src/config.h)

link_libraries(${FOTRAN_LIBS})
add_definitions(-DHAVE_CONFIG_H -DH5_USE_16_API -DAPPNAMESPACE=qmcplusplus -DMPICH_SKIP_MPICXX)

subdirs(src)
